package com.users.rn.rncommon.manager;

import android.app.Application;
import android.text.TextUtils;

import androidx.annotation.Nullable;
import com.facebook.react.ReactInstanceManager;
import com.users.rn.rncommon.model.PluginInfo;
import com.users.rn.rncommon.util.RNLogger;
import com.users.rn.rncommon.util.ReactConst;
import com.users.rn.rncommon.util.ReactUtils;

import java.util.HashMap;

/**
 * @Description:
 * @Author: bluce
 * @Date: 2020/12/3 10:50
 */
public final class ALHReactHostManager {
    private static final HashMap<String, ALHReactNativeHost> mCacheHosts = new HashMap<>();
    private Application mApplication;

    public ALHReactHostManager(Application application) {
        this.mApplication = application;
    }

    public ALHReactNativeHost getCommonReactNativeHost() {
        ALHReactNativeHost commonHost = mCacheHosts.get(ReactConst.COMMON_BUNDLE_PLUGIN_ID);
        if (commonHost != null) {
            mCacheHosts.remove(ReactConst.COMMON_BUNDLE_PLUGIN_ID);
            preLoaderNextCommonReactNativeHost();
        } else {
            commonHost = createCommonReactNativeHost();
            if (commonHost != null) {
                preLoaderNextCommonReactNativeHost();
            }
        }
        return commonHost;
    }

    public ALHReactNativeHost getBizReactNativeHost(PluginInfo pluginInfo) {
        if (pluginInfo == null || TextUtils.isEmpty(pluginInfo.getPluginId())) {
            return null;
        }
        ALHReactNativeHost nativeHost = mCacheHosts.get(pluginInfo.getPluginId());
        if (nativeHost == null) {
            if (pluginInfo.isUnpacking()) {//拆包，和common一个包
                nativeHost = getCommonReactNativeHost();
            } else {
                nativeHost = createReactNativeHost(pluginInfo);
            }
            if (nativeHost != null) {
                mCacheHosts.put(pluginInfo.getPluginId(), nativeHost);
            }
        }
        return nativeHost;
    }

    public void removeBizReactNativeHost(String pluginId) {
        if (!TextUtils.isEmpty(pluginId)) {
            mCacheHosts.remove(pluginId).clear();
        }
    }

    public ALHReactNativeHost getDebugHost() {
        return new ALHReactNativeHost(mApplication) {
            @Override
            public boolean getUseDeveloperSupport() {
                return true;
            }
        };
    }

    /**
     * 预加载下一个common RNHost
     */
    private void preLoaderNextCommonReactNativeHost() {
        ALHReactNativeHost commonReactNativeHost = createCommonReactNativeHost();
        if (commonReactNativeHost != null) {
            mCacheHosts.put(ReactConst.COMMON_BUNDLE_PLUGIN_ID, commonReactNativeHost);
        }
    }

    private ALHReactNativeHost createCommonReactNativeHost() {
        if (!ReactUtils.checkAssetsFileExist(mApplication, ReactConst.COMMON_BUNDLE_PATH)) {
            ReactUtils.log("createCommonReactNativeHost failed by " + ReactConst.COMMON_BUNDLE_PATH + " isn't exist");
//            ReactUtils.eventCommonBundle(mApplication);
            return null;
        }
        ALHReactNativeHost reactNativeHost = new ALHReactNativeHost(mApplication) {
            @Nullable
            @Override
            protected String getJSBundleFile() {
                return ReactConst.COMMON_BUNDLE_ASSETS_PATH;
            }
        };
/**
 * pre load
 *
 * mHasStartedCreatingInitialContext这个boolean值一旦调用了createReactContextInBackground就会被设置成true，由于不能重复创建上下文，所以一旦创建失败则丢弃该host
 * 但是源码中是在子线程throw的异常，无法捕捉
 */
        ReactInstanceManager reactInstanceManager = reactNativeHost.getReactInstanceManager();
        if (!reactInstanceManager.hasStartedCreatingInitialContext()) {
            reactInstanceManager.createReactContextInBackground();
        }
        return reactNativeHost;
    }

    private ALHReactNativeHost createReactNativeHost(PluginInfo pluginInfo) {
        if (pluginInfo == null || TextUtils.isEmpty(pluginInfo.getPluginId())) {
            return null;
        }
        final String bundlePath = pluginInfo.getBundlePath();
        ALHReactNativeHost nativeHost = null;
        if (!pluginInfo.isEventFlag()) {//走本地
            boolean isFileExisted = ReactUtils.checkAssetsFileExist(mApplication, bundlePath);
            if (isFileExisted) {
                nativeHost = new ALHReactNativeHost(mApplication) {
                    @Nullable
                    @Override
                    protected String getJSBundleFile() {
                        return bundlePath;
                    }
                };
            } else {
                RNLogger.e("createReactNativeHost failed, bundle file path is " + bundlePath);
            }
        } else {
            boolean isFileExisted = ReactUtils.checkSDCardFileExist(bundlePath);
            if (isFileExisted) {//先走sdCard
                nativeHost = new ALHReactNativeHost(mApplication) {
                    @Nullable
                    @Override
                    protected String getJSBundleFile() {
                        return bundlePath;
                    }
                };
            } else {
                //再走本地
                boolean isExisted = ReactUtils.checkAssetsFileExist(mApplication, bundlePath);
                if (isExisted) {
                    nativeHost = new ALHReactNativeHost(mApplication) {
                        @Nullable
                        @Override
                        protected String getJSBundleFile() {
                            return bundlePath;
                        }
                    };
                } else {
                    RNLogger.e("createReactNativeHost failed, bundle file path is " + bundlePath);
                }
            }
        }
        if (nativeHost != null) {
            ReactInstanceManager reactInstanceManager = nativeHost.getReactInstanceManager();
            if (!reactInstanceManager.hasStartedCreatingInitialContext()) {
                reactInstanceManager.createReactContextInBackground();
            }
        }
        return nativeHost;
    }
}
